package com.net.xpay.web.controller.merchant.safePay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.beust.jcommander.internal.Lists;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.MoneyUtil;
import com.net.xpay.common.manager.stat.UserDailyStatManager;
import com.net.xpay.core.domain.PayTransBatch;
import com.net.xpay.core.dto.AccountAmountCountDto;
import com.net.xpay.core.dto.SafePayBookAccountCountDto;
import com.net.xpay.core.enums.AlipayUserStatus;
import com.net.xpay.core.enums.SafePayBookAccountAuditStatus;
import com.net.xpay.core.manager.AlipayUserManager;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.manager.PayTransBatchManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.model.*;
import com.net.xpay.web.vo.SafePayBookAccountCountVo;
import com.net.xpay.web.vo.SafePayBookAccountInfoVo;
import com.net.xpay.web.vo.SafePayBookAccountVo;
import com.net.common.exception.BusinessException;
import com.net.common.model.ResultData;
import com.net.common.model.ResultList;
import com.net.common.model.ResultPagedList;
import com.net.xpay.alipay.safePay.PoseidonSafePayAlipayClient;
import com.net.xpay.common.domain.SafePayBusinessAuthAuditRecord;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.manager.SafePayBusinessAuthAuditRecordManager;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.domain.safePay.SafePayBookAccount;
import com.net.xpay.core.enums.SafePayBookAccountSignStatus;
import com.net.xpay.core.manager.safePay.SafePayBookAccountManager;
import com.net.xpay.core.service.safePay.SafePayBookAccountService;
import com.net.xpay.core.utils.BeanCopierUtil;
import com.net.xpay.web.secutiry.RequestUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**

 */
@RestController
@Slf4j
@RequestMapping("/merchant/safe-pay-book-account")
@Api(tags = "商户/支付宝账号", description = "商户 支付宝账号 net")
public class SafePayBookAccountController {

    @Autowired
    private SafePayBookAccountManager safePayBookAccountManager;

    @Autowired
    private SafePayBusinessAuthAuditRecordManager safePayBusinessAuthAuditRecordManager;

    @Autowired
    private PoseidonSafePayAlipayClient xpaySafePayAlipayClient;

    @Autowired
    private SafePayBookAccountService safePayBookAccountService;
    @Autowired
    private ChargeRecordManager chargeRecordManager;
    @Autowired
    private AlipayUserManager alipayUserManager;
    @Autowired
    private UserDailyStatManager userDailyStatManager;
    @Autowired
    private SafePayBatchManager safePayBatchManager;
    @Autowired
    private PayTransBatchManager payTransBatchManager;


    private ExecutorService executorService = Executors.newFixedThreadPool(64, new ThreadFactoryBuilder().setNameFormat("SafePayBookAccountController-%d").build());

    /**
     * 分页
     */
    @ApiOperation("分页")
    @PostMapping("/search")
    public ResultPagedList<SafePayBookAccountVo> search(@ApiIgnore @RequestUser User merchant, @RequestBody SafePayBookAccountSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        searchModel.setUserId(merchant.getId());
        if(searchModel.getSignStatus() == null){
            List<SafePayBookAccountSignStatus> statuses = Lists.newArrayList(SafePayBookAccountSignStatus.NORMAL, SafePayBookAccountSignStatus.TEMP);
            searchModel.setSignStatusList(statuses);
        }
        List<SafePayBookAccount> records = safePayBookAccountManager.search(searchModel);
        List<SafePayBookAccountVo> vos = BeanCopierUtil.batchCopy(SafePayBookAccount.class, SafePayBookAccountVo.class, records);

        for (SafePayBookAccountVo vo : vos) {
            if (vo.getBookId() == null || vo.getAgreementNo() == null) {
                vo.setCurrentDayTransLimit(new BigDecimal("0.00"));
                vo.setCurrentMonthTransLimit(new BigDecimal("0.00"));
                continue;
            }
            SafePayUserTransLimitModel safePayUserTransLimitModel =  safePayBookAccountService.getTransferLimit(merchant, vo.getId());
            vo.setCurrentDayTransLimit(safePayUserTransLimitModel.getCurrentDayTransLimit());
            vo.setCurrentMonthTransLimit(safePayUserTransLimitModel.getCurrentMonthTransLimit());
            if (!Strings.isNullOrEmpty(vo.getExtCardInfo())) {
                JSONObject jsonObject = JSON.parseObject(vo.getExtCardInfo());
                vo.setBankAccName(jsonObject.getString("bankAccName"));
                vo.setCardNo(jsonObject.getString("cardNo"));
                vo.setCardBank(jsonObject.getString("cardBank"));
                vo.setCardBranch(jsonObject.getString("cardBranch"));
                vo.setCardLocation(jsonObject.getString("cardLocation"));
                vo.setCardDeposit(jsonObject.getString("cardDeposit"));

                if (Strings.isNullOrEmpty(vo.getBankAccName())) {
                    vo.setBankAccName(jsonObject.getString("bank_acc_name"));
                    vo.setCardNo(jsonObject.getString("card_no"));
                    vo.setCardBank(jsonObject.getString("card_bank"));
                    vo.setCardBranch(jsonObject.getString("card_branch"));
                    vo.setCardLocation(jsonObject.getString("card_location"));
                    vo.setCardDeposit(jsonObject.getString("card_deposit"));
                }
            }

            AlipayFundAccountbookQueryResponse resp;
            try {
                resp = xpaySafePayAlipayClient.queryAlipayFundAccountbook(vo.getBookId(), vo.getAgreementNo());
                if (resp.isSuccess()) {
                    vo.setBookBalance(resp.getAvailableAmount());
                } else {
                    log.warn("query account failed|id={}", vo.getId());
                }
            } catch (AlipayApiException e) {
                log.warn("query account error|id={}", vo.getId(), e);
            }
        }

        long count = safePayBookAccountManager.searchCount(searchModel);

        return new ResultPagedList<>(vos, count, searchModel);
    }

    /**
     * 列表
     */
    @ApiOperation("列表")
    @PostMapping("/list")
    public ResultList<SafePayBookAccountVo> list(@ApiIgnore @RequestUser User merchant, @RequestBody SafePayBookAccountSearchModel searchModel)  {
        Preconditions.checkArgument(searchModel != null);
        searchModel.setUserId(merchant.getId());
        List<SafePayBookAccount> records = safePayBookAccountManager.list(searchModel);
        List<SafePayBookAccountVo> vos = BeanCopierUtil.batchCopy(SafePayBookAccount.class, SafePayBookAccountVo.class, records);

        List<Future<Void>> tasks = new ArrayList<>();
        for (SafePayBookAccountVo vo : vos) {
            if (vo.getBookId() == null || vo.getAgreementNo() == null) {
                vo.setBookBalance("0.00");
                continue;
            }

            Future<Void> task = executorService.submit(() -> {
                AlipayFundAccountbookQueryResponse resp;
                try {
                    resp = xpaySafePayAlipayClient.queryAlipayFundAccountbook(vo.getBookId(), vo.getAgreementNo());
                    if (resp.isSuccess()) {
                        vo.setBookBalance(resp.getAvailableAmount());
                    } else {
                        vo.setBookBalance("0.00");
                        log.warn("query account failed|id={}", vo.getId());
                    }
                } catch (AlipayApiException e) {
                    log.warn("query account error|id={}", vo.getId(), e);
                }
                return null;
            });
            tasks.add(task);
        }

        //同步一下
        for (Future<Void> f : tasks) {
            try {
                f.get();
            } catch (Exception e) {
                log.error("list safePayBookAccount get error",  e);
            }
        }

        vos.sort((o1, o2) -> new BigDecimal(o2.getBookBalance()).compareTo(new BigDecimal(o1.getBookBalance())));

        return new ResultList<>(vos);
    }

    /**
     * 查询已签约账户本金余额
     */
    @ApiOperation("查询已签约账户本金余额")
    @PostMapping("/query-all-signed-book-balance")
    public ResultData<String> queryAllSignedBookBalance(@ApiIgnore @RequestUser User merchant)  {
        SafePayBookAccountSearchModel searchModel = new SafePayBookAccountSearchModel();
        searchModel.setUserId(merchant.getId());
        searchModel.setSignStatus(SafePayBookAccountSignStatus.NORMAL);
        List<SafePayBookAccount> records = safePayBookAccountManager.list(searchModel);
        BigDecimal allBalance = new BigDecimal("0");
        for (SafePayBookAccount record : records) {
            AlipayFundAccountbookQueryResponse resp;
            try {
                resp = xpaySafePayAlipayClient.queryAlipayFundAccountbook(record.getBookId(), record.getAgreementNo());
                if (resp.isSuccess()) {
                    allBalance = allBalance.add(new BigDecimal(resp.getAvailableAmount()));
                } else {
                    log.warn("query account failed|account={}|userId={}|errorCode={}|errMsg={}", record.getAlipayNickName(), record.getUserId(), resp.getSubCode(), resp.getSubMsg());
                    throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "查询失败：请重试或联系客服");
                }
            } catch (AlipayApiException e) {
                log.warn("query account error|account={}|userId={}", record.getAlipayNickName(), record.getUserId(), e);
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "查询繁忙：请重试或联系客服");
            }

        }

        return new ResultData<>(allBalance.setScale(2, RoundingMode.HALF_UP).toString());
    }

    /**
     * 企业实名认证
     */
    @ApiOperation("企业实名认证")
    @PostMapping("/submit-business-authentication")
    public ResultData<Boolean> submitBusinessAuthentication(@ApiIgnore @RequestUser User merchant, @RequestBody SafePayBookAccountSubmitBusinessAuthModel model)  {
        Preconditions.checkArgument(model != null);
        safePayBookAccountService.submitBusinessAuthentication(merchant,model);
        return new ResultData<>(true);
    }

    /**
     * 根据id查询实名认证信息
     */
    @ApiOperation("根据id查询实名认证信息")
    @PostMapping("/get-info")
    public ResultData<SafePayBookAccountInfoVo> getBySafePayBookAccountId(@ApiIgnore @RequestUser User merchant, Long id)  {
        Preconditions.checkArgument(id != null);
        Long userId = merchant.getId();
        SafePayBookAccount safePayBookAccount = safePayBookAccountManager.findById(userId, id);

        SafePayBookAccountInfoVo safePayBookAccountInfoVo = new SafePayBookAccountInfoVo();
        BeanCopierUtil.copy(safePayBookAccount,safePayBookAccountInfoVo);

        SafePayBusinessAuthAuditRecord record = safePayBusinessAuthAuditRecordManager.findBySafePayBookAccountId(safePayBookAccount.getId());
        if (record != null) {
            safePayBookAccountInfoVo.setBizLicense(record.getBizLicense());
            safePayBookAccountInfoVo.setOtherOneImages(record.getOtherOneImages());
            safePayBookAccountInfoVo.setOtherTwoImages(record.getOtherTwoImages());
            safePayBookAccountInfoVo.setOtherThreeImages(record.getOtherThreeImages());
        }

        return new ResultData<>(safePayBookAccountInfoVo);
    }

    /**
     * 修改实名认证信息
     */
    @ApiOperation("修改实名认证信息")
    @PostMapping("/update-info")
    public ResultData<Boolean> updateSafePayBookAccount(@ApiIgnore @RequestUser User merchant,  Long id)  {
            safePayBookAccountService.updateSafePayBookAccount(merchant,id);

        return new ResultData<>(true);
    }
    /**
     * 修改备注
     */
    @ApiOperation("修改备注")
    @PutMapping("/remark")
    public ResultData<Boolean> updateRemark(@ApiIgnore @RequestUser User merchant, @RequestBody SafePayBookAccountUpdateModel updateModel) {
        Preconditions.checkArgument(updateModel != null && updateModel.getId() != null);
        if (Strings.isNullOrEmpty(updateModel.getRemark())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "备注不能为空");
        }
        if (updateModel.getRemark().length() > 16) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "备注最多16个字");
        }

        SafePayBookAccount safePayBookAccount = safePayBookAccountManager.findById(merchant.getId(), updateModel.getId());
        if (safePayBookAccount == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "安全发账户不存在");
        }

        safePayBookAccount.setRemark(updateModel.getRemark());
        safePayBookAccountManager.updateByPrimaryKeyWithVersion(safePayBookAccount);

        return new ResultData<>(true);
    }


    /**
     * 首页统计
     */
    @ApiOperation("首页统计")
    @PostMapping("/get-account-count")
    public ResultData<SafePayBookAccountCountVo> getAccountCount(@ApiIgnore @RequestUser User merchant) {
        //查询账号数量信息
        SafePayBookAccountSearchModel searchModel = new SafePayBookAccountSearchModel();
        searchModel.setUserId(merchant.getId());
        searchModel.setAuditStatus(SafePayBookAccountAuditStatus.NORMAL);
        SafePayBookAccountCountDto dto = safePayBookAccountManager.searchCountDto(searchModel);
        AlipayUserSearchModel alipayUserSearchModel = new AlipayUserSearchModel();
        alipayUserSearchModel.setUserId(merchant.getId());
        alipayUserSearchModel.setStatus(AlipayUserStatus.YES);
        Long accountNum = alipayUserManager.searchCount(alipayUserSearchModel);

        //查询统计转账金额
        // 根据当前时间获取改天的起始时间和结束时间
        LocalDateTime endTime = LocalDateUtil.getDayEnd(LocalDateTime.now());

        LocalDateTime startTime = LocalDateUtil.getDayStart(LocalDateTime.now());
        LocalDateTime dayTime = LocalDateUtil.getDayStart(LocalDateTime.now());
        LocalDateTime startMonthTime = LocalDateUtil.getMonthStartDay(LocalDateTime.now());
        //查询当月统计 不含今日
        SafePayBookAccountCountDto  monthAmountDto = userDailyStatManager.sumMonthAmount(startMonthTime,startTime,merchant.getId());
        //查询今日金额
        if (Objects.nonNull(monthAmountDto.getMonthTime()) && monthAmountDto.getMonthTime().plusDays(1).isBefore(startTime)) {
            startTime = monthAmountDto.getMonthTime().plusDays(1);
        }
        AccountAmountCountDto transAmount = payTransBatchManager.sumTransSuccessAmount(startTime, endTime, merchant.getId(),dayTime);
        AccountAmountCountDto safeSuccessAmount = safePayBatchManager.sumSafeSuccessAmount(startTime, endTime, merchant.getId(),dayTime);
        SafePayBookAccountCountVo vo = new SafePayBookAccountCountVo();
        vo.setSafeAccountNum(dto.getSafeAccountNum());
        vo.setSafeBusinessNum(dto.getSafeBusinessNum());
        vo.setAliAccountNum(accountNum);
        vo.setAliBusinessNum(accountNum);
        vo.setDayAmount(transAmount.getDayAmount().add(safeSuccessAmount.getDayAmount()));
        vo.setDayTime(endTime);
        vo.setMonthAmount(monthAmountDto.getMonthAmount().add(transAmount.getSumAmount()).add(safeSuccessAmount.getSumAmount()));
        vo.setMonthTime(endTime);
        vo.setId(merchant.getId());
        return new ResultData<>(vo);
    }

}
